package com.learning.crpc.provider;

import com.alibaba.fastjson.JSONObject;
import com.learning.crpc.model.CrpcRequest;
import com.learning.crpc.model.CrpcResponse;
import com.learning.crpc.protocol.NettyCodec;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoop;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.springframework.beans.BeansException;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.ContextStartedEvent;
import org.springframework.context.event.SmartApplicationListener;

import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @program: diy_rpc
 * @description:
 * @author: CaoYong
 * @create: 2021-07-01 13:40
 **/
public class NettyProviderServer implements SmartApplicationListener, ApplicationContextAware {

    ApplicationContext applicationContext;

    EventLoopGroup boss = new NioEventLoopGroup();
    EventLoopGroup worker = new NioEventLoopGroup();

    /**
     * 选择需要监听Spring启动事件和关闭事件
     * @param
     * @return
     */
    @Override
    public boolean supportsEventType(Class<? extends ApplicationEvent> eventTvpe) {
        return eventTvpe == ContextClosedEvent.class || eventTvpe == ContextStartedEvent.class || eventTvpe == ApplicationStartedEvent.class;
    }

    @Override
    public boolean supportsSourceType(Class<?> sourceType) {
        return true;
    }

    /**
     * 实现监听Spring服务启动事件，spring加载完毕后启动网络通信端口
     * @param applicationEvent
     */
    @Override
    public void onApplicationEvent(ApplicationEvent applicationEvent) {
        try {
            if (applicationEvent instanceof ApplicationStartedEvent) {
                ServerBootstrap serverBootstrap = new ServerBootstrap();
                serverBootstrap
                        .group(boss, worker)
                        .channel(NioServerSocketChannel.class)
                        .localAddress(new InetSocketAddress("127.0.0.1", 8081));

                serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline().addLast(new NettyCodec(CrpcRequest.class));
                        socketChannel.pipeline().addLast(new NettyProviderHandler(applicationContext));
                    }
                });
                serverBootstrap.bind().sync();
                System.out.println("完成端口绑定和服务端启动");

            }
        }catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    public int getOrder() {
        return 20;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
